// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: Implementation of some DOM wrappers that never got finished..
//   $Id$


#include "stdafx.h"
#include "XForms.h"
#include "resource.h"
#include "DOM3ASLS.h"
#include "XFormsApp.h"

extern CXFormsApp theApp;

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CDOMImplementationLS::CDOMImplementationLS()
{

}

CDOMImplementationLS::~CDOMImplementationLS()
{

}

CDOMBuilder* CDOMImplementationLS::createDOMBuilder(CDOMImplementationLS::EDOMImplementationLSMode eMode)
{
	CDOMBuilder* pDOMBuilder = new CDOMBuilder(eMode);

	return pDOMBuilder;
}

CDOMWriter* CDOMImplementationLS::createDOMWriter()
{
	CDOMWriter* pDOMWriter = new CDOMWriter();

	return pDOMWriter;
}

CDOMInputSource* CDOMImplementationLS::createDOMInputSource()
{
	CDOMInputSource* pDOMInputSource = new CDOMInputSource();

	return pDOMInputSource;
}

//CDOMBuilder


CDOMBuilder::CDOMBuilder(CDOMImplementationLS::EDOMImplementationLSMode eMode)
{
	switch (eMode)
	{
		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_SYNCHRONOUS:
		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_ASYNCHRONOUS:
			m_eMode = eMode;
			break;

		default:
			//[TODO] Throw an error
			break;
	}
}

CDOMBuilder::~CDOMBuilder()
{

}

void CDOMBuilder::setFeature(CDOMString pName, VARIANT_BOOL bState)
{
}

VARIANT_BOOL CDOMBuilder::canSetFeature(CDOMString pName, VARIANT_BOOL bState)
{
	return VARIANT_FALSE;
}

VARIANT_BOOL CDOMBuilder::getFeature(CDOMString pName)
{
	return VARIANT_FALSE;
}

CDOM3Document* CDOMBuilder::parseURI(CDOMString pUri)
{
	BOOL bIsSuccess = false;

	/*
	 * First create a DOM 3 ASLS document to hold the result
	 */

	CDocumentLS* pDocument = new CDocumentLS();

	switch (m_eMode)
	{
		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_SYNCHRONOUS:
			pDocument->m_bAsync = false;
			break;

		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_ASYNCHRONOUS:
			pDocument->m_bAsync = true;
			break;
	}

	/*
	 * Load the document with the required data
	 */

	bIsSuccess = pDocument->load(pUri);

//TODO: Check this - It must leak if !bIsSuccess -  is it ever called? - it should leak on the dbg heap
	if (!bIsSuccess)
		pDocument = NULL;

	return pDocument;
}

CDOM3Document* CDOMBuilder::parse(CDOMInputSource* pIs)
{
	BOOL bIsSuccess = false;

	/*
	 * First create a DOM 3 ASLS document to hold the result
	 */

	CDocumentLS* pDocument = new CDocumentLS();

	switch (m_eMode)
	{
		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_SYNCHRONOUS:
			pDocument->m_bAsync = false;
			break;

		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_ASYNCHRONOUS:
			pDocument->m_bAsync = true;
			break;
	}

	/*
	 * Load the document with the required data
	 */

	bIsSuccess = pIs->read(pDocument);
//TODO: Check this - It must leak if !bIsSuccess -  is it ever called? - it should leak on the dbg heap
	if (!bIsSuccess)
		pDocument = NULL;

	return pDocument;
}

void CDOMBuilder::parseWithContext(CDOMInputSource* pIs, IXMLDOMNode* pCnode, EActionTypes eAction)
{
	BOOL bIsSuccess = false;

	/*
	 * First create a DOM 3 ASLS document to hold the result
	 */

	CDocumentLS* pDocument = new CDocumentLS();

	switch (m_eMode)
	{
		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_SYNCHRONOUS:
			pDocument->m_bAsync = false;
			break;

		case CDOMImplementationLS::EDOMImplementationLSMode::MODE_ASYNCHRONOUS:
			pDocument->m_bAsync = true;
			break;
	}

	/*
	 * Load the document with the required data
	 */

	bIsSuccess = pIs->read(pDocument);

	if (bIsSuccess)
	{

		/*
		 * We now need to copy the results from our parser object to the context node
		 */

		CElement* pElement = NULL;

		// [TODO]
		// Implement all the DOM 3 Core methods ... this is a kludge
		pDocument->m_pXMLParser->get_documentElement(&pElement);
		//IXMLDOMNode* pParent = NULL;

		//pCnode->get_parentNode(&pParent);
		switch (eAction)
		{
			case ACTION_REPLACE:
				{
					//pParent->replaceChild(pElement, pCnode);
				}
				break;

			case ACTION_APPEND:
				{
					IXMLDOMNode* pNode = NULL;
					pCnode->appendChild(pElement, &pNode);
					::safeRelease(pNode);
					break;
				}
			case ACTION_INSERT_AFTER:
				{
				}
				break;

			case ACTION_INSERT_BEFORE:
				{
					//pParent->insertBefore(pElement, pCnode);
				}
				break;

			default:
				// [TODO] Throw an error
				break;
		}
		//pParent->Release();
		::safeRelease(pElement);
	}
	delete pDocument;
}

CDocumentLS::CDocumentLS()
{
	m_bAsync = false;
}

CDocumentLS::~CDocumentLS()
{

}

void CDocumentLS::abort()
{
}

BOOL CDocumentLS::load(CDOMString sUri)
{
	VARIANT_BOOL bIsSuccess = false;
	CComVariant v = sUri;

	m_pXMLParser->put_async(m_bAsync);
	m_pXMLParser->load(v, &bIsSuccess);

	//displaying errors is the duty of the calling application.
#if 0
	if (!bIsSuccess)
	{
		IXMLDOMParseError *pIParseError = NULL;
		HRESULT hr;

		hr = m_pXMLParser->get_parseError(&pIParseError);
		if (S_OK == hr)
		{
			if (pIParseError)
			{
				CComBSTR sReason,sText;

				hr = pIParseError->get_reason(&sReason);
				hr = pIParseError->get_srcText(&sText);
				if (SUCCEEDED(hr))
				{
					CString sMessage;
					sMessage.Format("Unable to open '%S': \nError: %S \n Text:%S",sUri,sReason,sText);
					theApp.reportError((char*)(LPCTSTR)sMessage);	
				}
				::safeRelease(pIParseError);
			}
		}
	}
#endif

	return bIsSuccess;
}

BOOL CDocumentLS::loadXML(CDOMString sSource)
{
	VARIANT_BOOL bIsSuccess = false;

	m_pXMLParser->put_async(false);
	
	m_pXMLParser->loadXML(sSource, &bIsSuccess);
//#if 0
	if(!bIsSuccess)
	{
		IXMLDOMParseError * e = NULL;
		CComBSTR s;
		m_pXMLParser->get_parseError(&e);
		e->get_reason(&s);
		e->get_srcText(&s);
		::safeRelease(e);
	}
//#endif
	return bIsSuccess;
}

CDOMString* CDocumentLS::saveXML(IXMLDOMNode* pSnode)
{
	CComBSTR bstrXML;

	if (pSnode)
		pSnode->get_xml(&bstrXML);
	else
		m_pXMLParser->get_xml(&bstrXML);

	CDOMString* pString = new CDOMString(bstrXML);
	bstrXML.Empty();
	return pString;
}


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDOMInputSource::CDOMInputSource()
{
	m_pByteStream = NULL;
	m_pCharacterStream = NULL;
	/*
	m_pStringData = NULL;
	m_pEncoding = NULL;
	m_pPublicId = NULL;
	m_pSystemId = NULL;
	m_pBaseURI = NULL;
	*/
}

CDOMInputSource::~CDOMInputSource()
{
	if(m_pByteStream) {
		delete m_pByteStream;
		m_pByteStream = 0;
	}
	if(m_pCharacterStream) {
		delete m_pCharacterStream;
		m_pCharacterStream = 0;
	}
	/*
	if (m_pStringData)
		delete m_pStringData;
	if (m_pEncoding)
		delete m_pEncoding;
	if (m_pPublicId)
		delete m_pPublicId;
	if (m_pSystemId)
		delete m_pSystemId;
	if (m_pBaseURI)
		delete m_pBaseURI;
		*/
}

BOOL CDOMInputSource::read(CDocumentLS* pDocument)
{
	BOOL bIsSuccess = false;

	if (m_pCharacterStream)
	{
		//[TODO] Read from the character stream
	}
	else if (m_pByteStream)
	{
		// [TODO] Don't quite understand how an InputStream can have a child of type
		// InputStream
	}
	else if (m_sStringData)
	{
		bIsSuccess = pDocument->loadXML(m_sStringData);
	}
	else if (m_sPublicId)
	{
		bIsSuccess = pDocument->load(m_sPublicId);
	}

	return bIsSuccess;
}
